﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;
using SyncList.Business.ValueObject;
using SyncList.Business.Helpers;
using SyncList.Business.Persistence;

namespace SyncList.UserInterface.ValueObject
{

    /// <summary>
    /// Toutes les données de l'explorateur
    /// </summary>
    public class ExplorerData : INotifyPropertyChanged
    {

        #region Attributs


        /// <summary>
        /// Collection d'items à afficher
        /// </summary>
        private List<ItemBase> _itemsSource = new List<ItemBase>();


        /// <summary>
        /// Liste des hashs de tous les fichiers que j'ai 
        /// </summary>
        private List<string> _myFilesHash = new List<string>();


        /// <summary>
        /// Collection d'items à afficher
        /// </summary>
        private ObservableCollection<ItemBase> _filteredItems = new ObservableCollection<ItemBase>();

        /// <summary>
        /// Base d'exploration
        /// </summary>
        private DirectoryContent _root;

        /// <summary>
        /// Chemin courant
        /// </summary>
        private DirectoryContent _currentDirectory = null;


        /// <summary>
        /// Taille des fichiers du dossier en cours
        /// </summary>
        private long _currentDirectorySize = 0;

        /// <summary>
        /// Taille des fichiers du dossier en cours
        /// </summary>
        private int _currentDirectoryCount = 0;

        /// <summary>
        /// Taille dans les dossiers
        /// </summary>
        private long _foldersSize = 0;


        /// <summary>
        /// Nombre total de fichiers à partir du dossier actuel
        /// </summary>
        private int _foldersFilesCount = 0;

        /// <summary>
        /// Parties du répertoire
        /// </summary>
        private ObservableCollection<DirectoryContent> _directoryParts = new ObservableCollection<DirectoryContent>();

        #endregion

        #region Constructeur

        /// <summary>
        /// Constructeur
        /// </summary>
        public ExplorerData()
        {
            //Initialize(new DirectoryContent(null, ""));
             Root = new DirectoryContent(null, "");
        }

        #endregion

        #region Accesseurs


        /// <summary>
        /// Collection d'items à afficher
        /// </summary>
        public ObservableCollection<ItemBase> FilteredItems
        {
            get { return (_filteredItems); }
        }



        /// <summary>
        /// Chemin courant
        /// </summary>
        public DirectoryContent CurrentDirectory
        {
            get { return (_currentDirectory); }
            set
            {               
                if (_currentDirectory != value)
                {                
                    // - Libérer
                    if (_currentDirectory != null)
                        _currentDirectory.ItemsChanged -= new EventHandler(CurrentDirectory_ItemsChanged);

                
                    // --- Sauter automatiquement au dossier suivant si l'on affecte un dossier ".."
                    DirectoryContent newValue = value;
                    if (value != null)
                    {
                        if ((newValue.DirectoryType == DirectoryTypeEnum.Back) && (value.Parent != null))
                            newValue = value.Parent;
                    }                   
                    _currentDirectory = newValue;
                    Refresh(_currentDirectory);

                    // - Abonner
                    if (_currentDirectory != null)
                        _currentDirectory.ItemsChanged += new EventHandler(CurrentDirectory_ItemsChanged);


                    OnPropertyChanged("CurrentDirectory");
                }
            }
        }



        /// <summary>
        /// Le répertoire courant a vu son contenu changer
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void CurrentDirectory_ItemsChanged(object sender, EventArgs e)
        {
            DirectoryContent directory = (DirectoryContent)sender;
            Refresh(directory);   
        }



        /// <summary>
        /// Mettre à jour la liste des fichiers et dossiers de l'emplacement courant
        /// </summary>
        /// <param name="currentDirectory"></param>
        public void Refresh(DirectoryContent currentDirectory)
        {
            int count = 0;
            //int foldersFilesCount = 0; // Compter aussi les fichiers dans les sous-dossiers
            long filesSize = 0;
            //long foldersSize = 0;


            _filteredItems.Clear();
            if (currentDirectory != null)
            {

                // - Créer la navigation de retour
                if (currentDirectory.Parent != null)
                {
                    DirectoryContent itemDirectory = new DirectoryContent(currentDirectory.Parent, "..");
                    itemDirectory.DirectoryType = DirectoryTypeEnum.Back;
                    _filteredItems.Add(itemDirectory);
                }

                // - Créer tous les items de la liste
                foreach (ItemBase item in currentDirectory.Items)
                {
                    FileItem file = item as FileItem;
                    if (file != null)
                    {
                        filesSize += file.Size;
                        count++;
                    }
                    _filteredItems.Add(item);
                }
                FilesSize = filesSize;
                FilesCount = count;

                DirectoryParts.Clear();
                DirectoryContent[] directories = currentDirectory.GetPathParts();
                foreach (DirectoryContent directory in directories)
                    DirectoryParts.Add(directory);
            }

            FilesSize = filesSize;
            FoldersSize = currentDirectory.Size; //foldersSize;
            FilesCount = count;
            FoldersFilesCount = currentDirectory.FileCount;
        }

        /// <summary>
        /// Mettre à jour
        /// </summary>
        public void Refresh()
        {
            Refresh(_currentDirectory);  
        }



        /// <summary>
        /// Taille des fichiers du dossier en cours
        /// </summary>
        public long FilesSize
        {
            get { return (_currentDirectorySize);  }
            set
            {
                _currentDirectorySize = value;
                OnPropertyChanged("FilesSize");
                OnPropertyChanged("FilesSizeCaption");
            }
        }

        
        /// <summary>
        /// Taille des fichiers du dossier en cours
        /// </summary>
        public string FilesSizeCaption
        {
            get { return (SizeHelper.FormatSize(_currentDirectorySize)); }
        
        }


           /// <summary>
        /// Taille des fichiers du dossier en cours
        /// </summary>
        public long FoldersSize
        {
            get { return (_foldersSize); }
            set
            {
                _foldersSize = value;
                OnPropertyChanged("FoldersSize");
                OnPropertyChanged("FoldersSizeCaption");
            }
        }

        
        /// <summary>
        /// Taille des fichiers du dossier en cours
        /// </summary>
        public string FoldersSizeCaption
        {
            get { return (SizeHelper.FormatSize(_foldersSize)); }
        
        }


        

        /// <summary>
        /// Taille des fichiers du dossier en cours
        /// </summary>
        public int FilesCount
        {
            get { return (_currentDirectoryCount); }
            set
            {
                _currentDirectoryCount = value;
                OnPropertyChanged("FilesCount");
            }
        }


        /// <summary>
        /// Nombre total de fichiers à partir du dossier actuel
        /// </summary>
        public int FoldersFilesCount
        {
            get { return (_foldersFilesCount); }
            set
            {
                _foldersFilesCount = value;
                OnPropertyChanged("FoldersFilesCount");
            }
        }


      

        /// <summary>
        /// Parties du répertoire
        /// </summary>
        public ObservableCollection<DirectoryContent> DirectoryParts
        {
            get { return (_directoryParts); }
        }



        /// <summary>
        /// Racine
        /// </summary>
        public DirectoryContent Root
        {
            get { return (_root); }
            set 
            {
                _root = value; 
                OnPropertyChanged("Root");

                CurrentDirectory = _root;
            }
        }

        #endregion

        #region Méthodes



        #endregion

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion



       
    }
}
